from __future__ import division
from urllib import urlopen
import re,threading,time,pickle,sys,contextlib

OOPS = []

class Item:

    List = {}

    def __init__ (self, name, req_lvl):

        self.name = name
        self.req_lvl = int(req_lvl)
        self.ID = "%s: Lvl %s" %(self.name, self.req_lvl)

        Item.List[self.ID] = self

def buildItem (URL, page):

    Valid = True
    try:
        with contextlib.closing(urlopen(URL)) as open_url:
            webpage = open_url.read()
    except IOError:
        OOPS.append(URL)

    # Start getting Item Data
    name_re = re.compile('<h2 class="caption">(.*)</h2>')
    required_level_re = re.compile('<dd class="db-requiredLevel">Required Level: (\d+)</dd>')
    defense_re = re.compile('<dd class="db-defense"><span>Defense:</span> (\d+)</dd>')


    try:
        item_name = re.findall(name_re, webpage)[0]
        req_lvl = re.findall(required_level_re, webpage)[0]
    except IndexError:
        Valid = False

    if Valid:
        name = re.sub(r'&#x27;',"'",item_name)
        item = Item(
            name, req_lvl)
        #sys.stdout.write("\rDownloading from page %s: %s%s" %(page, item.name, " "*20))
        #sys.stdout.flush()
    else:
        #print "%s Did not return an item!" %URL
        OOPS.append(URL)

def startScraping ():

    URL = "http://www.gw2db.com/items/armor"
    sys.stdout.write("Loading %s ..." % URL) ; sys.stdout.flush()
    with contextlib.closing(urlopen(URL)) as open_url:
        webpage = open_url.read()
    sys.stdout.write("Done!\n") ; sys.stdout.flush()

    page_count_pattern = re.compile(r'hellip.*class="b-pagination-item">(\d+)</a></li><li class="b-pagination-item">.*"next">')
    page_count = re.findall(page_count_pattern, webpage)
    print "Armor has a total of %s pages" %page_count[0]

    for page in xrange(int(page_count[0])):
        print "Now loading page %s" %(int(page)+1)
    #for page in xrange(1):
        try:
            current_page = urlopen("%s?page=%s" % (URL, str(page+1))).read()
        except IOError:
            continue
        item_listing_finder = re.compile('<a href="(.*)" class="gwitem gwitem-.*">.*</a>')
        item_listing = re.findall(
        item_listing_finder, current_page)
        for i in item_listing:
            time.sleep(2.66)
            #buildItem("http://www.gw2db.com%s" %i, page+1)
            threading.Thread(target=buildItem, args=("http://www.gw2db.com%s" %i,page+1)).start()

def checkForMatch (item, name):
    """ Compare each letter in item. If a match, return True, else False"""

    for x in xrange(len(name)):
        try:
            if item[x].lower() != name[x].lower():
                return False
        except IndexError:
            return False
    return True


def findMatch (name, item_list):
    """ Created for internal use in command completion. """

    possibles = []
    # Iterate over every item in the room until one comes up a match
    for item in item_list:
        if item == None:
            continue
        if item.lower() == name.lower():
            possibles = [item]
            return possibles
        if checkForMatch(item, name) == True:
            possibles.append(item)
    if len(possibles) == 0:
        return None
    else:
        return possibles

def search ():

    items = Item.List.keys()
    print "%s items in the database." %(len(items))
    sought = raw_input("Search: ")
    possibles = findMatch(sought, items)
    if possibles:
        print "Printing all possible matching items"
        for item in possibles:
            print item + ":"
            for attr in Item.List[item].__dict__.keys():
                print "\t%s: %s" %(attr, Item.List[item].__dict__[attr])
    else:
        print "\nNo matches found\n"

def saveData ():

    print "Saving!"
    while True:
        time.sleep(30)
        with open("armordb.pkl", "w") as f:
            pickle.dump(Item.List, f)
        with open("OOPS.pkl", "w") as f:
            pickle.dump(OOPS, f)

def prompt ():

    options = {"Build":startScraping, "Search":search}
    while True:
        for idx,option in enumerate(options.keys()):
            print "%s: %s" %(idx+1, option)
        choice = raw_input(": ")
        if not choice.isdigit(): continue
        else:
            threading.Thread(target=saveData).start()
            options[options.keys()[int(choice)-1]]()
            continue

if __name__ == "__main__":
    prompt()
    
